Add mouse pointer support to press and hold
authorWilliam Jon McCann <william.jon.mccann@gmail.com>
Wed, 24 Jul 2013 23:48:11 +0000 (19:48 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 5 Aug 2013 06:45:46 +0000 (08:45 +0200)
The internal class GtkPressAndHold was so far only
reacting to touch events. But in most cases where
a touch-and-hold or 'long press' pattern is useful,
click-and-hold can also be used.

This patch makes GtkPressAndHold react to mouse
clicks as well.

https://bugzilla.gnome.org/show_bug.cgi?id=704703

gtk/gtkpressandhold.c

index 0b4f35d0498acb4ab63187ebfa8b3a09ce9a14d6..5635c6caf0c078ccef34ca2fef286eb74dc12dc0 100644 (file)
@@ -28,6 +28,8 @@ struct _GtkPressAndHoldPrivate
   gint drag_threshold;
 
   GdkEventSequence *sequence;
+  GdkDevice *device;
+  guint button;
   guint timeout;
   gint start_x;
   gint start_y;
@@ -160,6 +162,8 @@ press_and_hold_cancel (GtkPressAndHold *pah)
 
   priv->timeout = 0;
   priv->sequence = NULL;
+  priv->device = NULL;
+  priv->button = 0;
 }
 
 static gboolean
@@ -181,17 +185,22 @@ gtk_press_and_hold_process_event (GtkPressAndHold *pah,
 {
   GtkPressAndHoldPrivate *priv = pah->priv;
 
-  /* We're already tracking a different touch, ignore */
+  /* We're already tracking a different input, ignore */
   if ((event->type == GDK_TOUCH_BEGIN && priv->sequence != NULL) ||
-      (event->type != GDK_TOUCH_BEGIN && priv->sequence != event->touch.sequence))
+      (event->type == GDK_BUTTON_PRESS && priv->device != NULL) ||
+      (event->type == GDK_TOUCH_UPDATE && priv->sequence != event->touch.sequence) ||
+      (event->type == GDK_TOUCH_END && priv->sequence != event->touch.sequence) ||
+      (event->type == GDK_TOUCH_CANCEL && priv->sequence != event->touch.sequence) ||
+      (event->type == GDK_BUTTON_RELEASE && priv->device != event->button.device) ||
+      (event->type == GDK_BUTTON_RELEASE && priv->button != event->button.button) ||
+      (event->type == GDK_MOTION_NOTIFY && priv->device != event->motion.device))
     return;
 
-  priv->x = event->touch.x;
-  priv->y = event->touch.y;
-
   if (event->type == GDK_TOUCH_BEGIN)
     {
       priv->sequence = event->touch.sequence;
+      priv->x = event->touch.x;
+      priv->y = event->touch.y;
       priv->start_x = priv->x;
       priv->start_y = priv->y;
       priv->timeout =
@@ -199,6 +208,8 @@ gtk_press_and_hold_process_event (GtkPressAndHold *pah,
     }
   else if (event->type == GDK_TOUCH_UPDATE)
     {
+      priv->x = event->touch.x;
+      priv->y = event->touch.y;
       if (ABS (priv->x - priv->start_x) > priv->drag_threshold ||
           ABS (priv->y - priv->start_y) > priv->drag_threshold)
         press_and_hold_cancel (pah);
@@ -212,6 +223,29 @@ gtk_press_and_hold_process_event (GtkPressAndHold *pah,
     {
       press_and_hold_cancel (pah);
     }
+  else if (event->type == GDK_BUTTON_PRESS)
+    {
+      priv->device = event->button.device;
+      priv->button = event->button.button;
+      priv->x = event->button.x;
+      priv->y = event->button.y;
+      priv->start_x = priv->x;
+      priv->start_y = priv->y;
+      priv->timeout =
+          gdk_threads_add_timeout (priv->hold_time, hold_action, pah);
+    }
+  else if (event->type == GDK_BUTTON_RELEASE)
+    {
+      press_and_hold_cancel (pah);
+    }
+  else if (event->type == GDK_MOTION_NOTIFY)
+    {
+      priv->x = event->motion.x;
+      priv->y = event->motion.y;
+      if (ABS (priv->x - priv->start_x) > priv->drag_threshold ||
+          ABS (priv->y - priv->start_y) > priv->drag_threshold)
+        press_and_hold_cancel (pah);
+    }
 }
 
 GtkPressAndHold *